﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;
using System.IO;
using System.Threading;

namespace ROOTFileSizeAnalyzer
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            ///
            /// If we are installed, start a check for updates
            /// 

            if (App.Current.InstallState == InstallState.Installed)
            {
                App.Current.CheckAndDownloadUpdateCompleted += new CheckAndDownloadUpdateCompletedEventHandler(Current_CheckAndDownloadUpdateCompleted);
                App.Current.CheckAndDownloadUpdateAsync();
            }

            ///
            /// Init the app
            /// 

            BranchInfo = new ObservableCollection<ROOTBranchInfo>();
            InitializeComponent();
        }

        /// <summary>
        /// The check for a new updated app has finished...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Current_CheckAndDownloadUpdateCompleted(object sender, CheckAndDownloadUpdateCompletedEventArgs e)
        {
            if (e.UpdateAvailable)
            {
                MessageBox.Show("An update to this application has been downloaded. It will be used next time you start the ROOT File Size Analyzer");
            }
        }

        /// <summary>
        /// Keep track of the main Popup, if we need it.
        /// </summary>
        private Popup _mainPopup = null;

        public ObservableCollection<ROOTBranchInfo> BranchInfo { get; set; }

        /// <summary>
        /// True when we are busy loading up something and we should have the busy indicator going.
        /// </summary>
        public bool IsBusyLoading
        {
            get { return (bool)GetValue(IsBusyLoadingProperty); }
            set { SetValue(IsBusyLoadingProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsBusyLoading.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsBusyLoadingProperty =
            DependencyProperty.Register("IsBusyLoading", typeof(bool), typeof(MainPage), new PropertyMetadata(false));

        /// <summary>
        /// Do the pop-up to load up the size info!
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoadSizeInfoButton_Click(object sender, RoutedEventArgs e)
        {
            if (CheckPopupFree())
            {
                string oldText = LoadOldData();

                var input = new InputSizeData();
                input.EnteredROOTSizeText = oldText;
                input.CancelButtonAccess.Click += (o, a) => ClosePopup();
                input.LoadButtonAccess.Click += (o, a) => { ClosePopup(); LoadSizeText(input.EnteredROOTSizeText); };
                input.MaxHeight = 400;

                _mainPopup.Child = input;
                _mainPopup.IsOpen = true;
                input.Focus();
            }
        }

        /// <summary>
        /// Load up the text we want to save!
        /// This is loaded in the background just incase it
        /// takes some time to load up the information.
        /// </summary>
        /// <param name="p"></param>
        private void LoadSizeText(string rootText)
        {
            ///
            /// If this is going to be a URL reference, then we need to be out of browser. This is to
            /// avoid having to deal with cross site scripting problems!
            /// 

            var parser = new ROOTSizeParser();
            if (parser.IsURLReference(rootText) && App.Current.InstallState != InstallState.Installed)
            {
                MessageBox.Show("To load ROOT TTree size information from a URL please close this dialog box and install the application by right-clicking and selecting 'Install...' (security issue)");
                return;
            }

            ///
            /// Notify the UI that we are getting busy
            ///

            IsBusyLoading = true;

            ///
            /// Submit the background thread to do the actual loading
            /// 

            var obs = parser.ParseInput(rootText);
            obs.ObserveOnDispatcher().Subscribe(
            newVal =>
            {
                if (CompletInfoGrid.ItemsSource != null)
                {
                    CompletInfoGrid.ItemsSource = null;
                    BranchInfo.Clear();
                }
                BranchInfo.Add(newVal);
            },
            error =>
            {
                MessageBox.Show("Error loading ROOT output: " + error.Message);
                IsBusyLoading = false;
            },
                () =>
                {
                    CompletInfoGrid.ItemsSource = BranchInfo;
                    if (BranchInfo.Count > 0)
                    {
                        SaveROOTSizeData(rootText);
                    }
                    IsBusyLoading = false;
                });
        }

        /// <summary>
        /// Save the data to local storage so we can start up auto with this data
        /// next time.
        /// </summary>
        /// <param name="rootText"></param>
        private void SaveROOTSizeData(string rootText)
        {
            using (var store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var file = store.CreateFile("lastUsedData.txt"))
                {
                    using (var twr = new StreamWriter(file))
                    {
                        twr.Write(rootText);
                    }
                }
            }
        }

        /// <summary>
        /// Load up the old data if we can, and display it.
        /// </summary>
        private void RestoreSavedDataTable()
        {
            string data = LoadOldData();

            if (data != null)
            {
                LoadSizeText(data);
            }

        }

        /// <summary>
        /// Loads the data from our "last used" file store.
        /// </summary>
        /// <returns></returns>
        private string LoadOldData()
        {
            string data = null;
            using (var store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (store.FileExists("lastUsedData.txt"))
                {
                    using (var file = store.OpenFile("lastUsedData.txt", FileMode.Open))
                    {
                        var reader = new StreamReader(file);
                        data = reader.ReadToEnd();
                    }
                }
            }
            return data;
        }

        /// <summary>
        /// Create the pop up if we need it, return false if it is already open doing something.
        /// </summary>
        /// <returns></returns>
        private bool CheckPopupFree()
        {
            if (_mainPopup == null)
            {
                _mainPopup = new Popup();
                _mainPopup.VerticalOffset = 25;
                _mainPopup.HorizontalOffset = 25;

                //LayoutRoot.Children.Add(_mainPopup);
                //_mainPopup.SetValue(Grid.RowProperty, 0);
                //_mainPopup.SetValue(Grid.RowSpanProperty, 3);
                //_mainPopup.SetValue(Grid.ColumnProperty, 0);
                //_mainPopup.SetValue(Grid.ColumnSpanProperty, 1);
            }

            return !_mainPopup.IsOpen;
        }

        /// <summary>
        /// Close the pop up if it is currently open, and free up the user control
        /// it was hosting for later work.
        /// </summary>
        private void ClosePopup()
        {
            if (_mainPopup != null && _mainPopup.IsOpen)
            {
                _mainPopup.IsOpen = false;
                _mainPopup.Child = null;
            }
        }

        /// <summary>
        /// We are up - load up the old data if we have any!
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            RestoreSavedDataTable();

            ///
            /// Look to see if we have been updated (as we might be offline!)
            /// 

            Application.Current.CheckAndDownloadUpdateCompleted += (s, evt) =>
            {
                if (evt.UpdateAvailable)
                {
                    MessageBox.Show("A new version of this application is availible and will be run next time you start it");
                }
            };
        }
    }
}
